/**
 * 统一错误处理工具
 * 提供友好的错误提示和处理方案
 */

class ErrorHandler {
  constructor() {
    this.errorCodes = {
      // 网络错误
      'NETWORK_ERROR': '网络连接失败',
      'TIMEOUT_ERROR': '请求超时',
      'SERVER_ERROR': '服务器错误',
      
      // 业务错误
      'PRODUCT_NOT_FOUND': '商品不存在或已下架',
      'INSUFFICIENT_POINTS': '积分不足',
      'OUT_OF_STOCK': '商品库存不足',
      'ORDER_FAILED': '订单创建失败',
      
      // 数据错误
      'DATA_FORMAT_ERROR': '数据格式错误',
      'VALIDATION_ERROR': '数据验证失败',
      
      // 权限错误
      'AUTH_ERROR': '认证失败',
      'PERMISSION_DENIED': '权限不足'
    }
    
    this.retryableErrors = [
      'NETWORK_ERROR',
      'TIMEOUT_ERROR',
      'SERVER_ERROR'
    ]
  }

  /**
   * 处理错误并显示友好提示
   * @param {Error|string} error - 错误对象或错误信息
   * @param {Object} context - 错误上下文
   * @param {Object} options - 处理选项
   */
  handleError(error, context = {}, options = {}) {
    const errorInfo = this.parseError(error)
    const friendlyMessage = this.getFriendlyMessage(errorInfo, context)
    
    console.error('错误处理:', {
      error: errorInfo,
      context,
      options
    })
    
    // 根据错误类型选择处理方式
    if (options.showModal) {
      this.showErrorModal(friendlyMessage, errorInfo, options)
    } else if (options.showToast !== false) {
      this.showErrorToast(friendlyMessage, options)
    }
    
    // 记录错误日志
    this.logError(errorInfo, context)
    
    return errorInfo
  }

  /**
   * 解析错误信息
   * @param {Error|string} error - 错误
   * @returns {Object} 解析后的错误信息
   */
  parseError(error) {
    if (!error) {
      return {
        code: 'UNKNOWN_ERROR',
        message: '未知错误',
        type: 'unknown'
      }
    }

    if (typeof error === 'string') {
      return {
        code: this.getErrorCode(error),
        message: error,
        type: this.getErrorType(error)
      }
    }

    if (error instanceof Error) {
      return {
        code: error.code || this.getErrorCode(error.message),
        message: error.message,
        type: this.getErrorType(error.message),
        stack: error.stack
      }
    }

    // 处理API响应错误
    if (error.response) {
      return {
        code: error.response.code || 'API_ERROR',
        message: error.response.message || '接口调用失败',
        type: 'api',
        status: error.response.status
      }
    }

    return {
      code: 'UNKNOWN_ERROR',
      message: error.toString(),
      type: 'unknown'
    }
  }

  /**
   * 根据错误信息推断错误代码
   * @param {string} message - 错误信息
   * @returns {string} 错误代码
   */
  getErrorCode(message) {
    if (!message) return 'UNKNOWN_ERROR'
    
    const lowerMessage = message.toLowerCase()
    
    if (lowerMessage.includes('timeout')) return 'TIMEOUT_ERROR'
    if (lowerMessage.includes('network') || lowerMessage.includes('连接')) return 'NETWORK_ERROR'
    if (lowerMessage.includes('500') || lowerMessage.includes('服务器')) return 'SERVER_ERROR'
    if (lowerMessage.includes('404') || lowerMessage.includes('不存在')) return 'PRODUCT_NOT_FOUND'
    if (lowerMessage.includes('积分不足')) return 'INSUFFICIENT_POINTS'
    if (lowerMessage.includes('库存') || lowerMessage.includes('缺货')) return 'OUT_OF_STOCK'
    if (lowerMessage.includes('订单')) return 'ORDER_FAILED'
    if (lowerMessage.includes('格式') || lowerMessage.includes('format')) return 'DATA_FORMAT_ERROR'
    if (lowerMessage.includes('验证') || lowerMessage.includes('validation')) return 'VALIDATION_ERROR'
    if (lowerMessage.includes('认证') || lowerMessage.includes('auth')) return 'AUTH_ERROR'
    if (lowerMessage.includes('权限') || lowerMessage.includes('permission')) return 'PERMISSION_DENIED'
    
    return 'UNKNOWN_ERROR'
  }

  /**
   * 获取错误类型
   * @param {string} message - 错误信息
   * @returns {string} 错误类型
   */
  getErrorType(message) {
    if (!message) return 'unknown'
    
    const lowerMessage = message.toLowerCase()
    
    if (lowerMessage.includes('network') || lowerMessage.includes('timeout')) return 'network'
    if (lowerMessage.includes('server') || lowerMessage.includes('500')) return 'server'
    if (lowerMessage.includes('data') || lowerMessage.includes('format')) return 'data'
    if (lowerMessage.includes('auth') || lowerMessage.includes('permission')) return 'auth'
    
    return 'business'
  }

  /**
   * 获取友好的错误提示
   * @param {Object} errorInfo - 错误信息
   * @param {Object} context - 错误上下文
   * @returns {string} 友好提示
   */
  getFriendlyMessage(errorInfo, context = {}) {
    const { code, message, type } = errorInfo
    
    // 优先使用预定义的友好提示
    if (this.errorCodes[code]) {
      return this.errorCodes[code]
    }
    
    // 根据错误类型提供通用提示
    switch (type) {
      case 'network':
        return '网络连接异常，请检查网络设置后重试'
      case 'server':
        return '服务暂时不可用，请稍后重试'
      case 'data':
        return '数据处理异常，请刷新页面重试'
      case 'auth':
        return '登录状态异常，请重新登录'
      case 'business':
        // 对于业务错误，尝试提供更具体的提示
        return this.getBusinessErrorMessage(message, context)
      default:
        return message || '操作失败，请稍后重试'
    }
  }

  /**
   * 获取业务错误的友好提示
   * @param {string} message - 原始错误信息
   * @param {Object} context - 错误上下文
   * @returns {string} 友好提示
   */
  getBusinessErrorMessage(message, context) {
    if (!message) return '操作失败，请稍后重试'
    
    // 根据上下文提供更精确的提示
    if (context.action === 'exchange') {
      if (message.includes('积分')) return '积分不足，无法完成兑换'
      if (message.includes('库存')) return '商品库存不足，请选择其他商品'
      return '兑换失败，请稍后重试'
    }
    
    if (context.action === 'load_product') {
      if (message.includes('不存在')) return '商品不存在或已下架'
      return '商品信息加载失败，请刷新重试'
    }
    
    // 清理技术性错误信息
    const cleanMessage = message
      .replace(/Error:/gi, '')
      .replace(/Exception:/gi, '')
      .replace(/\[.*?\]/g, '')
      .trim()
    
    return cleanMessage || '操作失败，请稍后重试'
  }

  /**
   * 显示错误提示框
   * @param {string} message - 错误信息
   * @param {Object} errorInfo - 错误详情
   * @param {Object} options - 选项
   */
  showErrorModal(message, errorInfo, options = {}) {
    const isRetryable = this.retryableErrors.includes(errorInfo.code)
    
    uni.showModal({
      title: options.title || '操作失败',
      content: message,
      confirmText: isRetryable ? '重试' : '确定',
      cancelText: isRetryable ? '取消' : '',
      showCancel: isRetryable,
      success: (res) => {
        if (res.confirm && isRetryable && options.onRetry) {
          options.onRetry()
        }
      }
    })
  }

  /**
   * 显示错误Toast
   * @param {string} message - 错误信息
   * @param {Object} options - 选项
   */
  showErrorToast(message, options = {}) {
    uni.showToast({
      title: message,
      icon: 'none',
      duration: options.duration || 3000,
      mask: options.mask || false
    })
  }

  /**
   * 记录错误日志
   * @param {Object} errorInfo - 错误信息
   * @param {Object} context - 错误上下文
   */
  logError(errorInfo, context) {
    const logData = {
      timestamp: new Date().toISOString(),
      error: errorInfo,
      context,
      userAgent: navigator.userAgent,
      url: window.location?.href || 'unknown'
    }
    
    // 在开发环境下输出详细日志
    if (process.env.NODE_ENV === 'development') {
      console.group('🚨 错误日志')
      console.error('错误信息:', errorInfo)
      console.log('错误上下文:', context)
      console.log('完整日志:', logData)
      console.groupEnd()
    }
    
    // 在生产环境下可以发送到日志服务
    // this.sendToLogService(logData)
  }

  /**
   * 判断错误是否可重试
   * @param {Object} errorInfo - 错误信息
   * @returns {boolean} 是否可重试
   */
  isRetryable(errorInfo) {
    return this.retryableErrors.includes(errorInfo.code)
  }

  /**
   * 获取错误的建议操作
   * @param {Object} errorInfo - 错误信息
   * @param {Object} context - 错误上下文
   * @returns {Array} 建议操作列表
   */
  getSuggestedActions(errorInfo, context = {}) {
    const actions = []
    
    switch (errorInfo.code) {
      case 'NETWORK_ERROR':
        actions.push('检查网络连接')
        actions.push('重试操作')
        break
      case 'TIMEOUT_ERROR':
        actions.push('检查网络速度')
        actions.push('稍后重试')
        break
      case 'INSUFFICIENT_POINTS':
        actions.push('查看积分获取方式')
        actions.push('选择其他商品')
        break
      case 'OUT_OF_STOCK':
        actions.push('选择其他商品')
        actions.push('设置到货提醒')
        break
      case 'PRODUCT_NOT_FOUND':
        actions.push('返回商品列表')
        actions.push('搜索相似商品')
        break
      default:
        actions.push('刷新页面')
        actions.push('稍后重试')
    }
    
    return actions
  }
}

// 创建全局实例
const errorHandler = new ErrorHandler()

// 导出便捷方法
export const handleError = (error, context, options) => {
  return errorHandler.handleError(error, context, options)
}

export const parseError = (error) => {
  return errorHandler.parseError(error)
}

export const getFriendlyMessage = (errorInfo, context) => {
  return errorHandler.getFriendlyMessage(errorInfo, context)
}

export const isRetryable = (errorInfo) => {
  return errorHandler.isRetryable(errorInfo)
}

export const getSuggestedActions = (errorInfo, context) => {
  return errorHandler.getSuggestedActions(errorInfo, context)
}

export default errorHandler